package com.hjr.leetcode.util.designMode;

import java.util.ArrayList;
import java.util.List;

// 创建者模式 (Creational Patterns)
// 1. 单例模式 (Singleton Pattern)
class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        //细节双端检锁、保证不重复初始化
        //线程进入判断条件之后，都会卡在锁释放的过程中，当第一个线程完成创建后，剩余线程可能会重复进入锁中，造成重复创建
        //所以需要两层判断
        //这种是懒汉模式、只要第一次用到才创建，性能比较好
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

// 2. 工厂方法模式 (Factory Method Pattern)
// 符合开闭原则、对扩展开放、修改关闭
// 降低解耦度
// 封装性好，不需要考虑创建过程，中间还可以执行扩展逻辑
// 符合单一职责
interface Product {
    void use();
}

class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

// 开发优势：耦合度低，只依赖实现类。支持动态切换和多态。
interface Factory {
    Product createProduct();
}

class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 3. 抽象工厂模式 (Abstract Factory Pattern)
// 和上面的工厂方法模式一样，抽象工厂模式会创建一系列相关对象，会包含多个创建方法
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

interface Button {
    void paint();
}

interface Checkbox {
    void paint();
}

class WinButton implements Button {
    @Override
    public void paint() {
        System.out.println("Windows Button");
    }
}

class WinCheckbox implements Checkbox {
    @Override
    public void paint() {
        System.out.println("Windows Checkbox");
    }
}

class MacButton implements Button {
    @Override
    public void paint() {
        System.out.println("Mac Button");
    }
}

class MacCheckbox implements Checkbox {
    @Override
    public void paint() {
        System.out.println("Mac Checkbox");
    }
}

class WinFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WinButton();
    }
    @Override
    public Checkbox createCheckbox() {
        return new WinCheckbox();
    }
}

class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }
    @Override
    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
}

// 4. 建造者模式 (Builder Pattern)
// 优势：创建复杂对象时，把创建过程封装起来，保证初始化按顺序执行。
//  符合开闭原则、单一原则、扩展性好
class Car {
    private String engine;
    private String wheels;
    private String color;
    
    public void setEngine(String engine) {
        this.engine = engine;
    }
    
    public void setWheels(String wheels) {
        this.wheels = wheels;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    // getters...
}

interface CarBuilder {
    void buildEngine();
    void buildWheels();
    void buildColor();
    Car getResult();
}

class SportsCarBuilder implements CarBuilder {
    private Car car = new Car();
    @Override
    public void buildEngine() {
        car.setEngine("Sports Engine");
    }
    @Override
    public void buildWheels() {
        car.setWheels("Sports Wheels");
    }
    @Override
    public void buildColor() {
        car.setColor("Red");
    }
    @Override
    public Car getResult() {
        return car;
    }
}

class CarDirector {
    public void construct(CarBuilder builder) {
        builder.buildEngine();
        builder.buildWheels();
        builder.buildColor();
    }
}

// 结构模式 (Structural Patterns)
// 5. 适配器模式 (Adapter Pattern)
class Adaptee {
    public void specificRequest() {
        System.out.println("Specific request");
    }
}

interface Target {
    void request();
}

class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

// 6. 装饰器模式 (Decorator Pattern)
interface Component {
    void operation();
}

class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("Concrete Component operation");
    }
}

class Decorator implements Component {
    protected Component component;
    
    public Decorator(Component component) {
        this.component = component;
    }
    @Override
    public void operation() {
        component.operation();
    }
}

class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }
    
    private void addedBehavior() {
        System.out.println("Added behavior A");
    }
}

// 7. 外观模式 (Facade Pattern)
class SubSystemA {
    public void operationA() {
        System.out.println("Subsystem A operation");
    }
}

class SubSystemB {
    public void operationB() {
        System.out.println("Subsystem B operation");
    }
}

class Facade {
    private SubSystemA subA = new SubSystemA();
    private SubSystemB subB = new SubSystemB();
    
    public void operation() {
        subA.operationA();
        subB.operationB();
    }
}

// 行为模式 (Behavioral Patterns)
// 8. 观察者模式 (Observer Pattern)
interface Observer {
    void update(String message);
}

interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers(String message);
}

class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<Observer>();
    private String state;

    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }
    @Override
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
    
    public void setState(String state) {
        this.state = state;
        notifyObservers(state);
    }
}

class ConcreteObserver implements Observer {
    private String name;
    
    public ConcreteObserver(String name) {
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println(name + " received: " + message);
    }
}

// 9. 策略模式 (Strategy Pattern)
interface Strategy {
    void algorithm();
}

class ConcreteStrategyA implements Strategy {
    @Override
    public void algorithm() {
        System.out.println("Algorithm A");
    }
}

class ConcreteStrategyB implements Strategy {
    @Override
    public void algorithm() {
        System.out.println("Algorithm B");
    }
}

class Context {
    private Strategy strategy;
    
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public void execute() {
        strategy.algorithm();
    }
}

// 10. 模板方法模式 (Template Method Pattern)
abstract class AbstractClass {
    public void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
        concreteOperation();
    }
    
    abstract void primitiveOperation1();
    abstract void primitiveOperation2();
    
    void concreteOperation() {
        System.out.println("Concrete operation");
    }
}

class ConcreteClass extends AbstractClass {
    @Override
    void primitiveOperation1() {
        System.out.println("Primitive operation 1");
    }
    @Override
    void primitiveOperation2() {
        System.out.println("Primitive operation 2");
    }
}

// 11. 命令模式 (Command Pattern)
interface Command {
    void execute();
}

class Receiver {
    public void action() {
        System.out.println("Receiver action");
    }
}

class ConcreteCommand implements Command {
    private Receiver receiver;
    
    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }
    @Override
    public void execute() {
        receiver.action();
    }
}

class Invoker {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void executeCommand() {
        command.execute();
    }
}

// 12. 状态模式 (State Pattern)
interface State {
    void handle(ContextState context);
}

class ConcreteStateA implements State {
    @Override
    public void handle(ContextState context) {
        System.out.println("Handling in State A");
        context.setState(new ConcreteStateB());
    }
}

class ConcreteStateB implements State {
    @Override
    public void handle(ContextState context) {
        System.out.println("Handling in State B");
        context.setState(new ConcreteStateA());
    }
}

class ContextState {
    private State state;
    
    public ContextState() {
        state = new ConcreteStateA();
    }
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void request() {
        state.handle(this);
    }
}

/**
 * 设计模式说明
 * 
 * 一、创建型模式 (Creational Patterns)
 * 1. 单例模式 (Singleton Pattern)
 *    - 目的：确保一个类只有一个实例，并提供一个全局访问点
 *    - 应用场景：数据库连接池、日志记录器、配置管理器等
 *    - 优点：节省内存，全局唯一，延迟初始化
 *    - 缺点：违背单一职责原则，难以扩展，可能造成内存泄漏
 * 
 * 2. 工厂方法模式 (Factory Method Pattern)
 *    - 目的：定义一个创建对象的接口，让子类决定实例化哪个类
 *    - 应用场景：创建复杂对象、框架开发
 *    - 优点：符合开闭原则，易于扩展
 *    - 缺点：增加系统复杂度，每增加一个产品类需要增加一个具体工厂类
 * 
 * 3. 抽象工厂模式 (Abstract Factory Pattern)
 *    - 目的：提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类
 *    - 应用场景：跨平台UI库、数据库访问层
 *    - 优点：保证产品族的一致性，易于切换产品族
 *    - 缺点：扩展困难，增加系统抽象性
 * 
 * 4. 建造者模式 (Builder Pattern)
 *    - 目的：将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示
 *    - 应用场景：创建复杂对象，如HTML文档、SQL查询等
 *    - 优点：封装性好，便于控制细节风险
 *    - 缺点：产生多余的Builder对象，产品内部变化复杂时难以应对
 * 
 * 二、结构型模式 (Structural Patterns)
 * 5. 适配器模式 (Adapter Pattern)
 *    - 目的：将一个类的接口转换成客户希望的另一个接口
 *    - 应用场景：系统扩展、封装第三方库、兼容老系统
 *    - 优点：提高类的复用性，增加类的透明度和复用性
 *    - 缺点：过多使用适配器会使系统凌乱，增加代码阅读难度
 * 
 * 6. 装饰器模式 (Decorator Pattern)
 *    - 目的：动态地给一个对象添加一些额外的职责
 *    - 应用场景：扩展一个类的功能、动态增加功能、动态撤销
 *    - 优点：继承的有力补充，比继承更灵活，可以通过多层嵌套实现复杂功能
 *    - 缺点：产生很多小对象，增加系统复杂度，调试困难
 * 
 * 7. 外观模式 (Facade Pattern)
 *    - 目的：为子系统中的一组接口提供一个一致的界面
 *    - 应用场景：设计初期为复杂子系统提供简单接口、层次化结构、维护遗留系统
 *    - 优点：简化客户端使用，解耦合，更好的划分访问层次
 *    - 缺点：增加新的子系统可能需要修改外观类，违背开闭原则
 * 
 * 三、行为型模式 (Behavioral Patterns)
 * 8. 观察者模式 (Observer Pattern)
 *    - 目的：定义对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新
 *    - 应用场景：事件处理系统、消息订阅、GUI事件处理
 *    - 优点：观察者和被观察者是抽象耦合的，建立一套触发机制
 *    - 缺点：如果一个被观察者对象有很多的直接和间接的观察者，将所有的观察者都通知到会花费很多时间
 * 
 * 9. 策略模式 (Strategy Pattern)
 *    - 目的：定义一系列算法，把它们一个个封装起来，并且使它们可相互替换
 *    - 应用场景：多个类只区别在表现行为不同、需要使用一个算法的不同变体、算法使用数据客户不应该知道的数据
 *    - 优点：算法可以自由切换，避免使用多重条件判断，扩展性良好
 *    - 缺点：策略类会增多，所有策略类都需要对外暴露
 * 
 * 10. 模板方法模式 (Template Method Pattern)
 *     - 目的：定义一个操作中的算法的骨架，而将一些步骤延迟到子类中
 *     - 应用场景：有多个子类共有的方法，且逻辑基本相同时、重要复杂的算法，把核心算法设计为模板方法
 *     - 优点：封装不变部分，扩展可变部分，提取公共代码，便于维护
 *     - 缺点：类数目的增加，增加了系统实现的复杂度
 * 
 * 11. 命令模式 (Command Pattern)
 *     - 目的：将一个请求封装为一个对象，从而使你可用不同的请求对客户进行参数化
 *     - 应用场景：GUI中操作的封装、日志记录、撤销操作
 *     - 优点：降低系统的耦合度，容易设计一个命令队列，容易实现Undo和Redo操作
 *     - 缺点：可能导致系统有过多的具体命令类
 * 
 * 12. 状态模式 (State Pattern)
 *     - 目的：允许一个对象在其内部状态改变时改变它的行为
 *     - 应用场景：行为随状态改变而改变的场景、条件、分支语句的代替者
 *     - 优点：封装了转换规则，枚举可能的状态，在枚举状态之前需要确定状态种类
 *     - 缺点：状态模式的使用必然会增加系统类和对象的个数
 */
public class DesignPatterns {
    public static void main(String[] args) {
        // 示例：单例模式
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println("Singleton instances are the same: " + (s1 == s2));
        
        // 示例：工厂方法模式
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.use();
        
        // 示例：观察者模式
        ConcreteSubject subject = new ConcreteSubject();
        Observer observer1 = new ConcreteObserver("Observer1");
        Observer observer2 = new ConcreteObserver("Observer2");
        
        subject.attach(observer1);
        subject.attach(observer2);
        subject.setState("New State");
        
        // 示例：策略模式
        Context context = new Context();
        context.setStrategy(new ConcreteStrategyA());
        context.execute();
        
        context.setStrategy(new ConcreteStrategyB());
        context.execute();
    }
}